home *** CD-ROM | disk | FTP | other *** search
- /*
- File: TextStylePrimitives.c
-
- Contains: QuickDraw GX to PostScript conversion code.
- File contains primitive routines for setting
- text styles, includeing font, size, and text-face.
-
- Version: Technology: Quickdraw GX 1.1.x
-
- Copyright: © 1990-1997 by Apple Computer, Inc., all rights reserved.
- */
-
- #include "GXToPSBuildConfig.h"
- #include <GXGraphics.h>
- #include "GXGraphicsPriv.h"
- #include <GXEnvironment.h>
- #include "GXToPostScript.h"
- #include "IOUtilities.h"
- #include "RDUtil.h"
- #include "FontHandler.h"
- #include "PublicPostScriptIE.h"
- #include "private.h"
- #include "PSIEResources.h"
- #include "GXErrors.h"
- #include "ShapeUtilities.h"
- #include <String.h>
-
- #ifdef resumeLabel
- #undef resumeLabel
- #endif
- #define resumeLabel(exception)
-
- /**********************************
-
- Routine tests to see if we should use
- the fast case of the BuildChar routine
- in the PostScript text face code.
-
- This case handles a subset of all text faces
- and implements white layers as drawing white
- rather than clipping so output is incorrect
- if drawn on top of other objects.
-
- ** KEEP IN SYNC WITH TEXTFACEPROCS.PS **
-
- LW8LayerBuildChar only ignores:
- outlineStyle (except pen width if framed layer)
- boldOutset
- whiteLayer transparency
- autoAdvance
-
- Current implementation only returns true for
- QuickDraw shadow text from translator for two
- byte fonts. (also, no autoAdvance)
-
- ***********************************/
- Boolean TestUseLW8BuildChar(gxTextFace *theFace, gxStyle theStyle);
- Boolean TestUseLW8BuildChar(gxTextFace *theFace, gxStyle theStyle)
- {
- #pragma unused(theFace)
-
- Style theQDStyle;
- long len;
- gxTag theTag;
- Boolean useIt = false;
-
-
- /* Auto Advance requires the general case BuildChar */
-
- if (GXGetStyleTextAttributes(theStyle) & gxAutoAdvanceText)
- return(false);
-
- /* See if style is tagged with QuickDraw style */
-
- if (GXGetStyleTags(theStyle, textFaceTagType, 1, gxSelectToEnd, nil) > 0) {
-
- GXGetStyleTags(theStyle, textFaceTagType, 1, 1, &theTag);
- len = GXGetTag(theTag, nil, &theQDStyle);
-
- check ( len == sizeof(Style) );
-
- if ( theQDStyle & shadow ) {
-
- /*
- Now check to see if the translation target was PostScript -
- if it isn't then we can't use optimized buildchar
- */
-
- if ( GXGetStyleTags(theStyle, targetTagType, 1, gxSelectToEnd, nil) > 0 ) {
-
- long target;
- GXGetStyleTags(theStyle, targetTagType, 1, 1, &theTag);
- len = GXGetTag(theTag, nil, &target);
-
- check ( len = sizeof(long) );
-
- if ( (target == 0) || (target == gxPostScriptTargetTranslation ) )
- useIt = true;
-
- } else {
-
- /* No target tag, let's assume we can use it - less risky of a change at this point 2/16/95 */
-
- useIt = true;
-
- }//end if
-
- }//end if
-
- }//end if
-
- return(useIt);
-
- }//TestUseLW8BuildChar
-
- //<FF>
- /**********************************
-
- Routine tests to see if a text face can be
- handled by the MakeSimpleLayeredFont PS proc.
-
- Can be if:
- 1. #layers == 1
- 2. AutoAdvance is false.
- 3. Layer is evenOdd or windingNumber filled
- 4. Layer has nil style
- 5. Layer has transform that has fullShape clip.
- 6. Layer's transform's mapping matches advance mapping.
- 7. Layer's Bold Outset is 0,0
-
- ************************************/
- Boolean TestSimpleFace(gxTextFace *theFace, gxStyle theStyle);
- Boolean TestSimpleFace(gxTextFace *theFace, gxStyle theStyle)
- {
- gxTransform aTransform;
- gxMapping aMapping;
- gxShapeFill layerFill;
-
- /* Check # 1 */
- if (theFace->faceLayers != 1)
- return(false);
-
- /* Check # 2 */
- if (GXGetStyleTextAttributes(theStyle) & gxAutoAdvanceText)
- return(false);
-
- /* check # 3 */
- layerFill = theFace->faceLayer[0].outlineFill;
- if ( (layerFill != gxEvenOddFill) && ( layerFill != gxWindingFill) )
- return(false);
-
- /* check # 4 */
- if (theFace->faceLayer[0].outlineStyle != nil)
- return(false);
-
- /* check #5 and #6 */
- aTransform = theFace->faceLayer[0].outlineTransform;
-
- if (aTransform != nil) {
-
- if (GetTransformClipType(aTransform) != gxFullType)
- return(false);
-
- GXGetTransformMapping(aTransform, &aMapping);
-
- if (!TestMappingEqual(&aMapping, &(theFace->advanceMapping) ) )
- return(false);
-
- } else { // nil transform means identity mapping for layer so test advance for identity too.
-
- if ( !TestMappingIdentity(&(theFace->advanceMapping)) )
- return(false);
-
- }//end if
-
- /* check #7 */
- if ( (theFace->faceLayer[0].boldOutset.x != 0) || (theFace->faceLayer[0].boldOutset.y != 0) )
- return(false);
-
-
- /* Passed all tests, return true */
-
- return(true);
-
- }//TestSimpleFace
-
-
- /************************************
- MakeTransformDict:
-
- Convert the gx graphics transform into a PostScript Dictionary
-
- If the transform is nil, then a transform dictionary
- for the identity transform will be generated.
-
- hIEGlobals: the Imaging Engine globals
- theTransform: The transform to translate.
-
- *************************************/
- OSErr MakeTransformDict(TIEGlobalsHdl hIEGlobals, gxTransform theTransform)
- {
- OSErr status = noErr;
- gxMapping theMapping;
- gxShape theClip;
- TRDParams* pRDParams;
- gxShapeType clipType;
- gxShapeFill clipFill;
- Boolean transformWasNil = false;
-
- if (theTransform == nil) {
- transformWasNil = true;
- theTransform = GXNewTransform();
- }//end if
-
-
- GXGetTransformMapping(theTransform, &theMapping);
- nrequire(TestMappingPerspective(&theMapping), failed_HasPerspective); // Remove eventually and support perspective.
-
- theClip = GXGetTransformClip(theTransform);
- clipType = GXGetShapeType(theClip);
- clipFill = GXGetShapeFill(theClip);
-
- pRDParams = (*hIEGlobals)->pRDParams;
-
-
- /** Put parameters for MakeTrDict on operand stack **/
-
- /*** The clip geometry procedure ***/
-
- status = GeometryDrone(hIEGlobals, theClip, eClipGeometry + eMakeProcedure, nil, 0);
- nrequire(status, failed_Geometry);
-
- /*** The clip fill key ***/
-
- status = DoFillKey(pRDParams, clipFill);
- nrequire(status, failed_Output);
-
- /** The Mapping, of course perspective is ignored **/
-
- pRDParams->resIndex = kDoMapping;
- status = RDResPrintf(pRDParams, theMapping.map[0][0], theMapping.map[0][1],
- theMapping.map[1][0], theMapping.map[1][1],
- theMapping.map[2][0], theMapping.map[2][1],
- theMapping.map[2][2]
- );
- nrequire(status, failed_Output);
-
-
- /** Now execute the MakeTrDict oprator, leaving a transform dictionary on the stack **/
-
- pRDParams->resIndex = kMakeTrDict;
- status = RDResPrintf(pRDParams);
- nrequire(status, failed_Output);
-
- if (transformWasNil)
- GXDisposeTransform(theTransform);
-
- status = GXGetGraphicsError(nil);
- ncheck(status);
-
- failed_Geometry:
- failed_Output:
-
- GXDisposeShape(theClip);
-
-
- failed_HasPerspective:
-
- return(status);
-
- }//MakeTransformDict
-
- //<FF>
- /**************************
- Routine MakeStyleDict:
-
-
- Routine converts a gx graphics style into
- a PostScript style dictionary.
-
- A nil style implies (could only come from a text face layer):
- dash, pattern, join, caps, all nil
- penSize: 0
- textSize: 1
-
- ****************************/
- OSErr MakeStyleDict(TIEGlobalsHdl hIEGlobals, gxStyle theStyle)
- {
- OSErr status;
- gxPatternRecord thePattern;
- gxDashRecord theDash;
- gxJoinRecord theJoin;
- long i; // An integer.
- gxStyleAttribute theAttributes;
- TRDParams *rdParams;
-
-
- rdParams = (*hIEGlobals)->pRDParams;
-
- if (theStyle != nil) {
-
- thePattern.pattern = nil;
- theDash.dash = nil;
- theJoin.join = nil;
-
- theAttributes = GXGetStyleAttributes(theStyle);
-
- /*** Put all of the parameters for MakeStyleDict on the operand stack ***/
-
- /*** Pattern dictionary ****/
-
- GXGetStylePattern(theStyle, &thePattern);
- if (thePattern.pattern != nil)
- status = MakePatternDict(hIEGlobals, &thePattern, theAttributes);
- else
- status = DoNull(rdParams);
-
- nrequire(status, failed_Dict);
-
-
- /**** right is in ****/
-
- rdParams->resIndex = kDoBoolean;
- status = RDResPrintf(rdParams, theAttributes & gxAutoInsetStyle ? (long)true : (long)false);
- nrequire(status, failed_Dict);
-
-
- /*** frame type ***/
-
- rdParams->resIndex = kDoInt;
- status = RDResPrintf(rdParams, GetPSFrameValue(theAttributes));
- nrequire(status, failed_Dict);
-
-
- /*** Dash dictionary ***/
-
- GXGetStyleDash(theStyle, &theDash);
- if (theDash.dash != nil)
- status = MakeDashDict(hIEGlobals, &theDash, theAttributes);
- else
- status = DoNull(rdParams);
-
- nrequire(status, failed_Dict);
-
- /**** pen thickness ****/
-
- rdParams->resIndex = kDoFixed;
- status = RDResPrintf(rdParams, GXGetStylePen(theStyle));
- nrequire(status, failed_Dict);
-
- /** line cap **/
-
- status = GetPSLineCap(theStyle, &i);
- nrequire(status, failed_Dict);
- if (i == -1) // must be a shape cap, treat it as butt for the style dict.
- i = 0;
- rdParams->resIndex = kDoInt;
- status = RDResPrintf(rdParams, i);
- nrequire(status, failed_Dict);
-
- /** line join **/
-
- GXGetStyleJoin(theStyle, &theJoin);
- i = GetPSLineJoin(&theJoin);
- if (i == -1) // must be a shape join, treat it as flat for the style dict.
- i = 0;
- rdParams->resIndex = kDoInt;
- status = RDResPrintf(rdParams, i);
- nrequire(status, failed_Dict);
-
- /** Miter limit **/
-
- rdParams->resIndex = kDoFixed;
- status = RDResPrintf(rdParams, SkiaMiterToPS(theJoin.miter, GXGetStylePen(theStyle)));
- nrequire(status, failed_Dict);
-
- /** grid fitting **/
-
- rdParams->resIndex = kDoBoolean;
- status = RDResPrintf(rdParams, theAttributes & gxDeviceGridStyle ? (long)true : (long) false);
- nrequire(status, failed_Dict);
-
-
- /** Do the text size **/
- rdParams->resIndex = kDoFixed;
- status = RDResPrintf(rdParams, GXGetStyleTextSize(theStyle));
- nrequire(status, failed_Dict);
-
- nrequire(status = GXGetGraphicsError(nil), failed_Dict);
-
- /**** Now make it all into a style dictionary, leave dict on operand stack *****/
-
- rdParams->resIndex = kMakeStyleDict;
- status = RDResPrintf(rdParams);
- ncheck(status);
-
- failed_Dict:
- failed_Cap:
- /** Dispose of any shapes accumulated in obtaining style stuff **/
-
- if (thePattern.pattern != nil)
- GXDisposeShape(thePattern.pattern);
-
- if (theDash.dash != nil)
- GXDisposeShape(theDash.dash);
-
- if (theJoin.join != nil)
- GXDisposeShape(theJoin.join);
-
- } else {
-
- /** the style passed in was nil, output the nil style dictionary **/
-
- rdParams->resIndex = knilStyleDict;
- status = RDResPrintf(rdParams);
- ncheck(status);
-
- }//end if
-
- return(status);
-
- }//MakeStyleDict
-
-
-
- /******************************
- Function: TestStyleFace
-
- Function returns true if the style
- contains a text face
-
- There is a text face if:
- the #layers > 0
- or
- the advance mapping is not identity.
-
- *******************************/
- Boolean TestStyleFace(gxStyle theStyle);
- Boolean TestStyleFace(gxStyle theStyle)
- {
- gxTextFace theFace;
- long nLayers;
- Boolean hasFace = true; // initialize to true, false is indicated by elimination.
-
- nLayers = GXGetStyleFace(theStyle, nil);
-
- if (nLayers == -1) { // undocumented feature.
-
- hasFace = false;
-
- } else if (nLayers == 0) { // If number of layers is 0, then check advance mapping.
-
- GXGetStyleFace(theStyle, &theFace);
-
- if (TestMappingIdentity(&(theFace.advanceMapping)))
- hasFace = false;
-
- } else if (GXGetStyleTags(theStyle, textFaceTagType, 1, gxSelectToEnd, nil) > 0 ) {
-
- gxTag theTag;
- Style theQDStyle;
- long len;
-
- /******
- If the textFaceTagType tag on the text face is simple underline, then
- we can lie and say there is no text face because the PS text
- face code doesn't do underlines anyway.
-
- This makes us go faster and avoids a 1 pixel clipping problem in
- the text face code for small point sizes
- ******/
-
- GXGetStyleTags(theStyle, textFaceTagType, 1, 1, &theTag);
- len = GXGetTag(theTag, nil, &theQDStyle);
- #if DEBUGLEVEL > 1
- if (len > sizeof(Style))
- dprintf(notrace, "Fatal error, tfac tag was not a QD Style, size: %d", len);
- #endif
-
- if (theQDStyle == underline)
- hasFace = false;
-
- }//end if
-
- return(hasFace);
-
- }//TestStyleFace
-
- //<FF>
- /*******************************
-
- MakeFaceFontName:
-
- Combines the font name with the
- text face tags so that text face
- fonts can be resused by the PostScript
- procedures.
-
- Example: Helvetica with bold face at 12 points would be:
- Helvetica$01$000C0000
-
- the $01 is the QD face.
- the $000C0000 is the Fixed point size.
-
- return value: Did the name get changed?
-
- ********************************/
- Boolean MakeFaceFontName(gxStyle theStyle, Str255 fontName);
- Boolean MakeFaceFontName(gxStyle theStyle, Str255 fontName)
- {
- Boolean changedIt = false;
- gxTag theTag;
- Style theQDStyle;
- long len;
- long nTags;
- long newLength;
- Fixed pointSize;
-
- /*****
- Combine the name passed in with the text face tag
- (QD style converted to hex appended to name)
- *****/
- nTags = GXGetStyleTags(theStyle, textFaceTagType, 1, gxSelectToEnd, nil);
- if (nTags > 0) {
-
- GXGetStyleTags(theStyle, textFaceTagType, 1, 1, &theTag);
- len = GXGetTag(theTag, nil, &theQDStyle);
- #if DEBUGLEVEL > 1
- if (len > sizeof(Style))
- dprintf(notrace, "Fatal error, tfac tag was not a QD Style, size: %d", len);
- #endif
-
- /* PS Procs don't do underlining so ignore */
- theQDStyle &= ~underline;
-
- len = fontName[0];
- newLength = len + 1 + 2 * sizeof(Style); // Add 1 for '$' and hex length of a style
- if (nTags > 1)
- newLength += 1 + 2 * sizeof(Fixed); // Add 1 for '$' and hex length of a Fixed.
-
- if (newLength <= 128) {
-
- fontName[len + 1] = '$';
- HexBlockMove(&theQDStyle, fontName + len + 2, sizeof(Style));
- fontName[0] += 1 + 2 * sizeof(Style);
-
- /* If there is a second tag, then it must be the Fixed point size combine the name */
- if (nTags > 1) {
-
- GXGetStyleTags(theStyle, textFaceTagType, 2, 1, &theTag);
- len = GXGetTag(theTag, nil, &pointSize);
- #if DEBUGLEVEL > 1
- if (len > sizeof(Fixed))
- dprintf(notrace, "Fatal error, 2nd tfac tag was not a fixed, size: %d", len);
- #endif
-
- len = fontName[0];
- fontName[len + 1] = '$';
- HexBlockMove((unsigned char*)&pointSize, fontName + len + 2, sizeof(Fixed));
- fontName[0] += 1 + 2 * sizeof(Fixed);
-
- }//end if
-
- changedIt = true;
-
- } else {
-
- #if DEBUGLEVEL > 1
- dprintf(trace, "Text Face name exceeded 128 characters, not caching");
- #endif
-
- }//end if
-
- }//end if
-
- return(changedIt);
-
- }//MakeFaceFontName
-
-
-
- /*******************************
-
- Function: OutputPSStyleMappedName
-
- Function outputs a name for the potential
- font to substitute for the style which is
- stored in the 'gxPostscriptFontNameSynonymTag' tag.
-
- ********************************/
- OSErr OutputPSStyleMappedName(TIEGlobalsHdl hIEGlobals, gxStyle theStyle);
- OSErr OutputPSStyleMappedName(TIEGlobalsHdl hIEGlobals, gxStyle theStyle)
- {
- OSErr status;
- unsigned char fontName[130];
- TRDParams *rdParams;
- gxTag theTag;
- long len;
-
- if (GXGetStyleTags(theStyle, gxPostscriptFontNameSynonymTag, 1, gxSelectToEnd, nil) > 0) {
-
- GXGetStyleTags(theStyle, gxPostscriptFontNameSynonymTag, 1, 1, &theTag);
- len = GXGetTag(theTag, nil, nil);
- check (len <= 128);
-
- GXGetTag(theTag, nil, fontName + 1);
-
- fontName[0] = '/'; // prefix with slash.
- fontName[len + 1] = ' '; // space seperator.
- len += 2;
-
- } else {
-
- memcpy(fontName, "/GXNoName", 9);
- len = 9;
-
- }//end if
-
- rdParams = (*hIEGlobals)->pRDParams;
- rdParams->resIndex = kDoString;
- status = RDResPrintf(rdParams, fontName, len);
- ncheck(status);
-
- return(status);
-
- }//OutputPSStyleMappedName
-
-
- //<FF>
- /****************************************
-
- ApplyLayerTransformToRect
-
- Routine finds the new rectangle that
- encloses the rectangle passed in, mapped
- by the transform.
-
- tr: Transform to use.
- rect: Array of 2 points, first is top-left, second is bottom-right.
-
- *****************************************/
- void ApplyLayerTransformToRect(gxTransform tr, gxRectangle *rect);
- void ApplyLayerTransformToRect(gxTransform tr, gxRectangle *rect)
- {
- gxPoint rectPoints[4];
- gxMapping map;
- long i;
-
- if (tr == nil)
- return;
-
- /* Make the 4 points of the rectangle */
-
- // top-left
- rectPoints[0].x = rect->left;
- rectPoints[0].y = rect->top;
-
- // top-right.
- rectPoints[1].x = rect->right;
- rectPoints[1].y = rect->top;
-
- // bottom-right.
- rectPoints[2].x = rect->right;
- rectPoints[2].y = rect->bottom;
-
- // bottom-left.
- rectPoints[3].x = rect->left;
- rectPoints[3].y = rect->bottom;
-
- /* map them */
-
- MapPoints( GXGetTransformMapping(tr, &map), 4, rectPoints);
-
- /* Now find the bounding box of the four points */
- rect->left = rectPoints[0].x;
- rect->right = rect->left;
- rect->top = rectPoints[0].y;
- rect->bottom = rect->top;
-
- for (i = 1; i <= 3; ++i) {
-
- if (rectPoints[i].x < rect->left)
- rect->left = rectPoints[i].x;
-
- if (rectPoints[i].x > rect->right)
- rect->right = rectPoints[i].x;
-
- if (rectPoints[i].y < rect->top)
- rect->top = rectPoints[i].y;
-
- if (rectPoints[i].y > rect->bottom)
- rect->bottom = rectPoints[i].y;
-
- }//end for
-
- }//ApplyLayerTransformToRect
-
- //<FF>
- /****************************************
-
- OutputFaceBoundingBox:
-
- Function outputs the bounding box of the text face
- as a PostScript array
-
- ******************************************/
- OSErr OutputFaceBoundingBox(TIEGlobalsHdl hIEGlobals, gxStyle theStyle, gxTextFace *pFace);
- OSErr OutputFaceBoundingBox(TIEGlobalsHdl hIEGlobals, gxStyle theStyle, gxTextFace *pFace)
- {
- OSErr status;
- TRDParams *rdParams;
- gxFontVariation *variations = nil;
- long axisCount;
- gxRectangle fontBBox, faceBBox;
- gxRectangle layerRect;
- Fixed temp;
- gxFaceLayer *pLayer;
- long idx;
-
- rdParams = (*hIEGlobals)->pRDParams;
-
- axisCount = GXGetStyleFontVariationSuite(theStyle, nil);
- if (axisCount > 0) {
-
- status = PrNewPtr((Ptr *) &variations, axisCount * sizeof(gxFontVariation) );
- nrequire(status, failed_newPtr);
-
- GXGetStyleFontVariationSuite(theStyle, variations);
-
- }//endif
-
- GXPrivateGetFontBounds(GXGetStyleFont(theStyle), axisCount, variations, &fontBBox);
-
- #if DEBUGLEVEL > 1
- status = RDFlushBuffer(rdParams->rdMap);
- if (status == noErr)
- status = (*hIEGlobals)->psDevice->BufferData("% original: ", 12, gxNoBufferOptions);
- if (status == noErr) {
- rdParams->resIndex = kDoBBox;
- status = RDResPrintf(rdParams, fontBBox.left, fontBBox.top, fontBBox.right, fontBBox.bottom);
- nrequire(status, failed_Output);
- }
- #endif
-
- /* Negate the Y's and swap top and bottom because Font coordinate system is flipped from gx graphics */
-
- temp = fontBBox.top;
- fontBBox.top = -fontBBox.bottom;
- fontBBox.bottom= -temp;
-
-
- if ( (fontBBox.top != 0) || (fontBBox.bottom != 0) || (fontBBox.left != 0) || (fontBBox.right != 0) ) {
-
- /** Now properly produce the text face's bounding box by applying the layer's information to the font's bbox **/
-
- faceBBox = fontBBox;
- pLayer = pFace->faceLayer;
- for (idx = 0; idx < pFace->faceLayers; ++idx, ++pLayer) {
-
- /* Compute the bounding box if layer has a fill */
-
- if (pLayer->outlineFill != gxNoFill) {
-
- /** Compute layer's bounding box, start with font's bounding box **/
-
- layerRect = fontBBox;
-
- /* Scale the layer's bounding by the layer's point size */
-
- if (pLayer->outlineStyle != nil) {
-
- Fixed size = GXGetStyleTextSize(pLayer->outlineStyle);
-
- layerRect.left = FixedMultiply(layerRect.left, size);
- layerRect.top = FixedMultiply(layerRect.top, size);
- layerRect.right = FixedMultiply(layerRect.right, size);
- layerRect.bottom = FixedMultiply(layerRect.bottom, size);
-
- }//end if
-
-
- /** Expand layer's bounding box by boldness **/
-
- layerRect.left -= pLayer->boldOutset.x;
- layerRect.right += pLayer->boldOutset.x;
- layerRect.top -= pLayer->boldOutset.y;
- layerRect.bottom += pLayer->boldOutset.y;
-
- /* If framed, expand by pen and dash bounding box */
-
- if ( (pLayer->outlineFill == gxFrameFill) || (pLayer->outlineFill == gxClosedFrameFill) ) {
-
- if (pLayer->outlineStyle != nil) {
-
- Fixed pen = GXGetStylePen(pLayer->outlineStyle);
-
- if (DoesStyleHaveDash(pLayer->outlineStyle)) {
-
- gxDashRecord aDash;
- gxRectangle bounds;
-
- GXGetStyleDash(pLayer->outlineStyle, &aDash);
- GXGetShapeBounds(aDash.dash, 0, &bounds);
-
- pen = FixedMultiply(pen, bounds.bottom - bounds.top);
-
- GXDisposeShape(aDash.dash);
-
- }//end if
-
- layerRect.left -= pen / 2;
- layerRect.right += pen / 2;
- layerRect.top -= pen / 2;
- layerRect.bottom += pen / 2;
-
- }//end if
-
- }//end if
-
- /* Run the points through the layer's transform */
-
- ApplyLayerTransformToRect(pLayer->outlineTransform, &layerRect);
-
- /** Now add the layer's bounding box to the face's bounding box **/
-
- /* Left must be minimum of X's */
-
- if (layerRect.left < faceBBox.left)
- faceBBox.left = layerRect.left;
-
- if (layerRect.right < faceBBox.left)
- faceBBox.left = layerRect.right;
-
-
- /* Right must be maximum of X's */
-
- if (layerRect.right > faceBBox.right)
- faceBBox.right = layerRect.right;
-
- if (layerRect.left > faceBBox.right)
- faceBBox.right = layerRect.left;
-
-
- /* Top must be mimimum of Y's */
-
- if (layerRect.top < faceBBox.top)
- faceBBox.top = layerRect.top;
-
- if (layerRect.bottom < faceBBox.top)
- faceBBox.top = layerRect.bottom;
-
-
- /* Bottom must be maximum of Y's */
-
- if (layerRect.bottom > faceBBox.bottom)
- faceBBox.bottom = layerRect.bottom;
-
- if (layerRect.top > faceBBox.bottom)
- faceBBox.bottom = layerRect.top;
-
-
- }//end if Layer isn't noFill
-
- }//end for
-
- /****
- Negate the Y's and swap top and bottom again to put back into font space
- (Which then gets flipped again by PostScript later - how confusing)
- ****/
-
- temp = faceBBox.top;
- faceBBox.top = -faceBBox.bottom;
- faceBBox.bottom= -temp;
-
- /** Output the bounding box as an object on the operand stack **/
-
- rdParams->resIndex = kDoBBox;
- status = RDResPrintf(rdParams, faceBBox.left, faceBBox.top, faceBBox.right, faceBBox.bottom);
- nrequire(status, failed_Output);
-
- } else {
-
- /** Font could not tell me bounding box, put null on operand stack **/
-
- status = DoNull(rdParams);
- nrequire(status, failed_Output);
-
- }//end if
-
- failed_Output:
-
- if (variations != nil)
- DisposePtr((Ptr)variations);
-
- failed_newPtr:
-
- return(status);
-
- }//OutputFaceBoundingBox
-
- //<FF>
- /****************************************
-
- Routine: OutputSimpleFaceParams
-
- Routine outputs the parameters for a simple text
- face as defined by the MakeSimpleLayeredFont procedure.
-
- It can handle simple, one layer text faces that involve
- only an outlineTransform in the layer.
-
- ******************************************/
- OSErr OutputSimpleFaceParams(TIEGlobalsHdl hIEGlobals, gxTextFace *pFace, gxStyle theStyle);
- OSErr OutputSimpleFaceParams(TIEGlobalsHdl hIEGlobals, gxTextFace *pFace, gxStyle theStyle)
- {
- #pragma unused(theStyle)
-
- OSErr status;
- gxMapping layerMapping;
- TRDParams *rdParams;
- gxFaceLayer *pLayer;
-
- rdParams = (*hIEGlobals)->pRDParams;
-
- /* Output the layer's mapping */
-
- pLayer = pFace->faceLayer;
- if (pLayer->outlineTransform == nil)
- ResetMapping(&layerMapping);
- else
- GXGetTransformMapping(pLayer->outlineTransform, &layerMapping);
-
- rdParams->resIndex = kDoMapping;
- status = RDResPrintf(rdParams, layerMapping.map[0][0], layerMapping.map[0][1],
- layerMapping.map[1][0], layerMapping.map[1][1],
- layerMapping.map[2][0], layerMapping.map[2][1],
- layerMapping.map[2][2]
- );
-
- nrequire(status, failed_Output);
-
- failed_Output:
-
- return(status);
-
- }//OutputSimpleFaceParams
-
-
- //<FF>
- /****************************************
-
- Routine: OutputGeneralFaceParams
-
- Routine outputs the parameters for a general text
- face as defined by the MakeLayeredFont procedure.
-
- ******************************************/
- OSErr OutputGeneralFaceParams(TIEGlobalsHdl hIEGlobals, gxTextFace *pFace, gxStyle theStyle, Str255 fontName);
- OSErr OutputGeneralFaceParams(TIEGlobalsHdl hIEGlobals, gxTextFace *pFace, gxStyle theStyle, Str255 fontName)
- {
- OSErr status;
- TRDParams *rdParams;
- gxFaceLayer *pLayer;
- long nLayers;
- long i;
- gxStyle aStyle;
-
- rdParams = (*hIEGlobals)->pRDParams;
-
- /*** Put the parameters (except for the font name) for MakeLayeredFont on the operand stack ***/
-
- /** The font name from the 'gxPostscriptFontNameSynonymTag' tag **/
-
- status = OutputPSStyleMappedName(hIEGlobals, theStyle);
- nrequire(status, failed_Output);
-
-
- /** The font name for the text face font **/
-
- rdParams->resIndex = kFaceFontName;
- if (MakeFaceFontName(theStyle, fontName)) {
- nrequire(status = RDResPrintf(rdParams, fontName), failed_Output);
- } else {
- nrequire(status = RDResPrintf(rdParams, "\pDontCache"), failed_Output);
- }//end if
-
- /* Roll the 2 names behind the base font dictionary so operand stack is: name name fontDict */
-
- rdParams->resIndex = k3minus1Roll;
- nrequire(status = RDResPrintf(rdParams), failed_Output);
-
-
- /** The font bounding box **/
-
- status = OutputFaceBoundingBox(hIEGlobals, theStyle, pFace);
- nrequire(status, failed_Output);
-
- /** The auto advance **/
-
- rdParams->resIndex = kDoBoolean;
- nrequire(status = RDResPrintf(rdParams, GXGetStyleTextAttributes(theStyle) & gxAutoAdvanceText ? (long)true : (long)false), failed_Output);
-
- /** Now do the advance mapping **/
-
- rdParams->resIndex = kDoMapping;
- status = RDResPrintf(rdParams, pFace->advanceMapping.map[0][0], pFace->advanceMapping.map[0][1],
- pFace->advanceMapping.map[1][0], pFace->advanceMapping.map[1][1],
- pFace->advanceMapping.map[2][0], pFace->advanceMapping.map[2][1],
- pFace->advanceMapping.map[2][2]
- );
- nrequire(status, failed_Output);
-
-
- /***
- Now put the array of layers on the stack, an empty array will
- be on the stack if the number of layers was zero
- ***/
-
- nrequire(status = DoBeginArray(hIEGlobals), failed_Output);
-
- nLayers = pFace->faceLayers;
- pLayer = pFace->faceLayer;
- for (i = 0; i < nLayers; ++i, ++pLayer) {
-
- /** Put the parameters for MakeLayerDict on the stack **/
-
- /* the Layer fill key */
-
- if (pLayer->flags & gxClipLayer) // Treat clip layers as no fill since they are only for underlining.
- pLayer->outlineFill = gxNoFill;
-
- nrequire(status = DoFillKey(rdParams, pLayer->outlineFill), failed_Output);
-
- /* The white layer bit */
-
- rdParams->resIndex = kDoBoolean;
- nrequire(status = RDResPrintf(rdParams, pLayer->flags & gxWhiteLayer ? (long)true : (long)false), failed_Output);
-
- /* The style dictionary */
-
- aStyle = pLayer->outlineStyle;
- nrequire(status = MakeStyleDict(hIEGlobals, aStyle), failed_Output);
-
- /* The transform dictionary */
-
- nrequire(status = MakeTransformDict(hIEGlobals, pLayer->outlineTransform), failed_Output);
-
- /****
- The boldness:
-
- Make sure that there isn't a zero bold value unless they are both zero
- Since Boldness is done in PostScript by scaling, a zero value will cause
- an undefinedresult error. If they are both zero, qd2show ignores however
- ******/
-
- if ((pLayer->boldOutset.x != 0) || (pLayer->boldOutset.y != 0)) {
-
- if (pLayer->boldOutset.x == 0)
- pLayer->boldOutset.x = 0x00000010; // A very small number.
-
- if (pLayer->boldOutset.y == 0)
- pLayer->boldOutset.y = 0x00000010; // A very small number.
-
- }//end if
-
- rdParams->resIndex = kDoPoint;
- nrequire(status = RDResPrintf(rdParams, &(pLayer->boldOutset)), failed_Output);
-
- /* Execute the MakeLayerDict procedure, leaving the layer dictionary on the stack */
-
- rdParams->resIndex = kMakeLayerDict;
- nrequire(status = RDResPrintf(rdParams), failed_Output);
-
- }//end for
-
- nrequire(status = DoEndArray(hIEGlobals), failed_Output);
-
-
- /* Output boolean for which buildChar to use */
-
- rdParams->resIndex = kDoBoolean;
- nrequire(status = RDResPrintf(rdParams, (long)TestUseLW8BuildChar(pFace, theStyle)), failed_Output);
-
- failed_Output:
-
- return(status);
-
- }//OutputGeneralFaceParams
-
-
- //<FF>
- /********************************
-
- Function: MakeOptimalPStextFace
-
- Routine makes sure the text face is optimized for
- PostScript if it came from the quickdraw world.
-
- *********************************/
- OSErr MakeOptimalPSTextFace(gxStyle theStyle);
- OSErr MakeOptimalPSTextFace(gxStyle theStyle)
- {
- OSErr status = noErr;
- gxTag theTag;
- long len;
- Style theQDStyle;
-
- if (GXGetStyleTags(theStyle, textFaceTagType, 1, gxSelectToEnd, nil) > 0) {
-
- GXGetStyleTags(theStyle, textFaceTagType, 1, 1, &theTag);
- len = GXGetTag(theTag, nil, &theQDStyle);
-
- check ( len == sizeof(Style) );
-
- /*
- Now check to see if the translation target was PostScript -
- if it isn't Let's make it so.
- */
-
- if ( GXGetStyleTags(theStyle, targetTagType, 1, gxSelectToEnd, nil) > 0 ) {
-
- long target;
- GXGetStyleTags(theStyle, targetTagType, 1, 1, &theTag);
- len = GXGetTag(theTag, nil, &target);
-
- check ( len = sizeof(long) );
-
- if ( target != gxPostScriptTargetTranslation ) {
-
- #if DEBUGLEVEL > 1
- dprintf(trace, "Not spooled for PS, Calling TRSetStyleCommonFace: face: %X, size: %F", theQDStyle, GXGetStyleTextSize(theStyle));
- #endif
-
- TRSetStyleCommonFace( theStyle, (longCommonFace)theQDStyle, GXGetStyleTextSize(theStyle), fixed1, true, 0);
- status = GXGetGraphicsError(nil);
- ncheck(status);
-
- }//end if
-
- }//end if
-
- }//end if
-
-
- return(status);
-
- }//MakeOptimalPSTextFace
-
-
- //<FF>
- /*******************************
-
- Function: OutputFaceParams
-
- Function puts all of the parameters excluding the base font
- dictonary on the operand stack for MakeLayeredFont. The
- base font dictionary is on the stack.
-
- hIEGlobals: the imaging engine globals.
- theStyle: the style containing the text face.
- fontName: the name of the font we are applying the text face to.
-
- ********************************/
- OSErr OutputFaceParams(TIEGlobalsHdl hIEGlobals, gxStyle theStyle, Str255 fontName );
- OSErr OutputFaceParams(TIEGlobalsHdl hIEGlobals, gxStyle theStyle, Str255 fontName )
- {
- OSErr status;
- TIEGlobalsPtr pGlobals;
- gxTextFace *pFace;
- gxFaceLayer *pLayer;
- long nLayers;
- long i;
- TRDParams *rdParams;
-
- /** Make sure we get the best possible text face for PostScript performance **/
-
- status = MakeOptimalPSTextFace(theStyle);
- nrequire(status, failed_OptimalFace);
-
- /** Get workspace for the text face data structure **/
-
- nLayers = GXGetStyleFace(theStyle, nil);
- status = PSSetWorkSpaceSize(hIEGlobals, sizeof(gxTextFace) + nLayers * sizeof(gxFaceLayer) );
- nrequire(status, failed_SetWorkSpaceSize);
-
- pGlobals = *hIEGlobals;
- rdParams = pGlobals->pRDParams;
-
- /** Get the text face data **/
-
- HLock(pGlobals->hWorkSpace);
- pFace = (gxTextFace*)*(pGlobals->hWorkSpace);
- GXGetStyleFace(theStyle, pFace);
-
-
- if ( TestSimpleFace(pFace, theStyle) ) {
-
- status = OutputSimpleFaceParams(hIEGlobals, pFace, theStyle);
- nrequire(status, failed_SimpleFace);
-
- rdParams->resIndex = kMakeSimpleLayeredFont;
- status = RDResPrintf(rdParams);
- nrequire(status, failed_MakeSimpleFace);
-
- } else {
-
- status = OutputGeneralFaceParams(hIEGlobals, pFace, theStyle, fontName);
- nrequire(status, failed_GeneralFace);
-
- rdParams->resIndex = kTextFaceFont;
- status = RDResPrintf(rdParams);
- nrequire(status, failed_MakeGeneralFace);
-
- }//end if
-
- failed_MakeGeneralFace:
- failed_GeneralFace:
- failed_MakeSimpleFace:
- failed_SimpleFace:
-
- /*** Dispose of any graphics objects created by GXGetStyleFace ***/
-
- nLayers = pFace->faceLayers;
- pLayer = pFace->faceLayer;
- for (i = 0; i < nLayers; ++i, ++pLayer) {
-
- if (pLayer->outlineTransform != nil)
- GXDisposeTransform(pLayer->outlineTransform);
-
- if (pLayer->outlineStyle != nil)
- GXDisposeStyle(pLayer->outlineStyle);
-
- }//end for
-
- failed_Dispose:
-
- {
- OSErr saveStatus;
- saveStatus = PSReleaseWorkSpace(hIEGlobals);
- if (status == noErr)
- status = saveStatus;
- }
- ncheck(status);
-
- failed_SetWorkSpaceSize:
-
- failed_OptimalFace:
-
- return(status);
-
- }//OutputFaceParams
-
-
- //<FF>
- /*******************************
- Routine: EqualTextFace
-
- Routine compares two text styles to
- see if the text faces are equal.
-
- This may not be the most robust way of
- doing it. A gx graphics call would be nice.
-
- Warning: Can move memory due to internal allocation.
-
- *********************************/
- OSErr EqualTextFace(TIEGlobalsHdl hIEGlobals, Boolean *areEqual, gxStyle style1, gxStyle style2);
- OSErr EqualTextFace(TIEGlobalsHdl hIEGlobals, Boolean *areEqual, gxStyle style1, gxStyle style2)
- {
- OSErr status;
- TIEGlobalsPtr pGlobals;
- long nLayers1, nLayers2;
- gxStyle styleCopy;
- gxTextFace *pFace2;
- long faceSize;
-
- if (style1 == style2) {
- *areEqual = true;
- return(noErr);
- }//end if
-
- if ((style1 == nil) || (style2 == nil)) {
- *areEqual = false;
- return(noErr);
- }//end if
-
- if (GXEqualStyle(style1, style2)) {
- *areEqual = true;
- return(noErr);
- }//end if
-
-
- nLayers1 = GXGetStyleFace(style1, nil);
- nLayers2 = GXGetStyleFace(style2, nil);
-
- if ( (nLayers1 == -1) && (nLayers2 == -1) ) { // Neither has a face.
- *areEqual = true;
- return(noErr);
- }//end if
-
- if (nLayers1 != nLayers2) { // different number of layers.
- *areEqual = false;
- return(noErr);
- }//end if
-
- /** If we got here, then they both have faces with same # of layers and we must compare them **/
-
- faceSize = sizeof(gxTextFace) + nLayers1 * sizeof(gxFaceLayer);
-
- status = PSSetWorkSpaceSize(hIEGlobals, faceSize);
- nrequire(status, failed_SetSize);
-
- pGlobals = *hIEGlobals;
- HLock(pGlobals->hWorkSpace);
-
- pFace2 = (gxTextFace*)*(pGlobals->hWorkSpace);
- GXGetStyleFace(style2, pFace2);
-
- /** Make a copy of style 1 with style-2's text face. ***/
-
- styleCopy = GXCopyToStyle(nil, style1);
- nrequire(status = GXGetGraphicsError(nil), failed_CopyStyle);
- GXSetStyleFace(styleCopy, pFace2);
-
- *areEqual = GXEqualStyle(style1, styleCopy);
-
- GXDisposeStyle(styleCopy);
-
- failed_CopyStyle:
- {
- register OSErr saveStatus = PSReleaseWorkSpace(hIEGlobals);
- ncheck(saveStatus);
-
- if (status == noErr)
- status = saveStatus;
-
- }//end block
-
- failed_SetSize:
- return(status);
-
- }//EqualTextFace
-
- //<FF>
- /*******************************
- Routine: EqualVariations
-
- Routine compares two text styles to
- see if the variations are equal.
-
- Warning: Can move memory due to internal allocation.
-
- *********************************/
- OSErr EqualVariations(TIEGlobalsHdl hIEGlobals, Boolean *areEqual, gxStyle style1, gxStyle style2);
- OSErr EqualVariations(TIEGlobalsHdl hIEGlobals, Boolean *areEqual, gxStyle style1, gxStyle style2)
- {
- OSErr status;
- TIEGlobalsPtr pGlobals;
- long nVars1, nVars2;
- gxFontVariation *pVariation1, *pVariation2;
- TFontHandlerContext fhContext;
-
- /* First do the simple tests */
-
- if (style1 == style2) {
- *areEqual = true;
- return(noErr);
- }//end if
-
- if ((style1 == nil) || (style2 == nil)) {
- *areEqual = false;
- return(noErr);
- }//end if
-
- if (GXEqualStyle(style1, style2)) {
- *areEqual = true;
- return(noErr);
- }//end if
-
- /* All calls to get variations go through the font handler wrappers, it knows best */
-
- fhContext = (*hIEGlobals)->fhContext;
-
- status = FontHandlerGetStyleFontVariations(fhContext, style1, &nVars1, nil);
- nrequire(status, failed_FHGetVarCount1);
-
- status = FontHandlerGetStyleFontVariations(fhContext, style2, &nVars2, nil);
- nrequire(status, failed_FHGetVarCount2);
-
- if ( (nVars1 == 0) && (nVars2 == 0) ) { // Neither has a variation.
- *areEqual = true;
- return(noErr);
- }//end if
-
- if (nVars1 != nVars2) { // different number of axes.
- *areEqual = false;
- return(noErr);
- }//end if
-
- /** If we got here, then they both have same number of variations, so get them **/
-
- status = PSSetWorkSpaceSize(hIEGlobals, 2 * nVars1 * sizeof(gxFontVariation) );
- nrequire(status, failed_SetSize);
-
- pGlobals = *hIEGlobals;
- HLock(pGlobals->hWorkSpace);
-
- pVariation1 = (gxFontVariation*)*(pGlobals->hWorkSpace);
- pVariation2 = pVariation1 + nVars1; // don't you love C pointer arithmetic?
-
- status = FontHandlerGetStyleFontVariations(fhContext, style1, nil, pVariation1);
- nrequire(status, failed_getVar1);
-
- status = FontHandlerGetStyleFontVariations(fhContext, style2, nil, pVariation2);
- nrequire(status, failed_getVar2);
-
- /* and compare them */
- if ( memcmp( pVariation1, pVariation2, nVars1 * sizeof(gxFontVariation) ) == 0 )
- *areEqual = true;
- else
- *areEqual = false;
-
- failed_getVar1:
- failed_getVar2:
- {
- register OSErr saveStatus = PSReleaseWorkSpace(hIEGlobals);
- ncheck(saveStatus);
-
- if (status == noErr)
- status = saveStatus;
-
- }//end block
-
- failed_SetSize:
- failed_FHGetVarCount2:
- failed_FHGetVarCount1:
-
- return(status);
-
- }//EqualVariations
-
-
-
-
-
- //<FF>
- /*******************************
-
- Function: TextStylePrimitive
-
- Sets the current text style in the current
- graphics state. A text style, as far as PostScript
- is concerned includes the tangent - since this requires
- making a new font dictionary.
-
- hIEGLobals: imaging engine globals handle.
- textStyle: style for this piece of text.
- pTangent: tangent vector for this piece of text.
-
- *********************************/
- OSErr _TextStylePrimitive(TIEGlobalsHdl hIEGlobals, gxStyle textStyle, gxPoint* pTangent)
- {
- OSErr status; // error?
- TIEGlobalsPtr pGlobals; // dereference the globals.
- Fixed fontSize; // point size for font.
- Fixed a, b, c, d; // Parameters for SFt PostScript procedure.
- fhFont theFont; // font resource id.
- long child; // Child font index.
- Str255 fontName; // name of the font to set on the printer.
- TRDParams *rdParams; // RD Parameter block.
- Boolean hasFace; // Does it have a text face?
- Boolean fontSwapped = false; // Did we do a font change?
- Boolean facesEqual; // is text face the same as before?
- Boolean variationsEqual; // are the font variations same sas before?
- TFHSaveResult fhSaveResult; // save-level result from the font handler.
-
- status = FontHandlerGetStyleFont((*hIEGlobals)->fhContext, textStyle, &theFont);
- nrequire(status, failed_getfont);
-
- fontSize = GXGetStyleTextSize(textStyle);
-
- pGlobals = *hIEGlobals;
- rdParams = pGlobals->pRDParams;
-
- /*****
- Always make sure the font is avalialble, even if it is the same font as before
- cause a restore could have happened and flushed it
- *******/
-
- /** MakeFontAvailable can send the buffer data message **/
- status = RDFlushBuffer(rdParams->rdMap);
- nrequire(status, failed_rdFlush);
-
- status = FontHandlerMakeFontAvailable(pGlobals->fhContext, textStyle, &child, fontName, &fhSaveResult);
- nrequire(status, failed_FHMFA);
-
- status = EqualTextFace(hIEGlobals, &facesEqual, (*hIEGlobals)->textStyle, textStyle);
- nrequire(status, failed_EqualFace);
-
- status = EqualVariations(hIEGlobals, &variationsEqual, (*hIEGlobals)->textStyle, textStyle);
- nrequire(status, failed_EqualVariations);
-
- /**************
- Deal with font handler memory state, in case it did a save or a restore
- or a combination restore/save
- **************/
- if (fhSaveResult != fhNoChange) {
-
- status = FixGraphicsState(hIEGlobals, (fhSaveResult & fhDidRestore) ? true : false,
- (fhSaveResult & fhDidSave) ? true : false);
- nrequire(status, failed_FixGraphicsState);
-
- }//end if
-
-
- /************
- Do the text style:
-
- First make sure the current font dictionary reflects all of the
- style craziness such as variations and text faces.
-
- Second, deal with the font size and tangent.
-
- ************/
-
- hasFace = TestStyleFace(textStyle);
-
- pGlobals = *hIEGlobals; // In case the handle moved.
-
- if ( (pGlobals->theFont != theFont) || (pGlobals->fontChild != child) ||
- (!facesEqual) || (!variationsEqual) || (pGlobals->ieStateFlags & eFontOutOfDate) ) {
-
- /* Get the font dictionary on the stack */
-
- rdParams->resIndex = kFindFont;
- status = RDResPrintf(rdParams, fontName);
- nrequire(status, failed_FindFont);
-
- /** Update the font and child state in our globals **/
-
- pGlobals = *hIEGlobals;
- pGlobals->theFont = theFont;
- pGlobals->fontChild = child;
-
- /* Apply any variations to it */
-
- status = RDFlushBuffer(rdParams->rdMap); // calling font handler can send buffer data.
- nrequire(status, failed_rdFlush1);
- status = FontHandlerOutputVariationPSOperator((*hIEGlobals)->fhContext, textStyle);
- nrequire(status, failed_variations);
-
- /* Apply any text face to it */
-
- if (hasFace) {
-
- status = OutputFaceParams(hIEGlobals, textStyle, fontName);
- nrequire(status, failed_Face);
-
- }//end if
-
- /* Make the font with the text face and variations applied to it into the current base font */
-
- rdParams->resIndex = kSetBaseFont;
- nrequire(status = RDResPrintf(rdParams), failed_SetBaseFont);
- fontSwapped = true;
-
- }//end if
-
-
- /*** If necessary, apply the tangent/size combination to the base font in our state ****/
-
- pGlobals = *hIEGlobals;
-
- if ( (pGlobals->fontSize != fontSize) ||
- (pGlobals->fontTangent.x != pTangent->x) ||
- (pGlobals->fontTangent.y != pTangent->y) ||
- fontSwapped ) {
-
- pGlobals->fontSize = fontSize;
- pGlobals->fontTangent = *pTangent;
-
- /*****
- if the font swapped flag is true, then the above operations left the base font
- dictionary on the stack. If it is false, we must get it out of the augmented
- graphics state.
- *****/
- if (!fontSwapped) {
-
- rdParams->resIndex = kCurrBaseFont;
- nrequire(status = RDResPrintf(rdParams), failed_SelectFont);
-
- }//end if
-
- /** Apply the tangent to the base font on the operand stack **/
-
- // Construct the parameters for the SFt operator. (Text face font dicts are flipped in y so deal)
-
- a = FixedMultiply( pTangent->x, fontSize);
- b = FixedMultiply( pTangent->y, fontSize);
- c = FixedMultiply(-pTangent->y, fontSize); if (!hasFace) c = -c;
- d = FixedMultiply( pTangent->x, fontSize); if (!hasFace) d = -d;
-
- rdParams->resIndex = kTangentFont;
- nrequire(status = RDResPrintf(rdParams, a, b, c, d), failed_SelectFont);
-
- }//end if
-
- /** Update the text style in our global state **/
-
- pGlobals = *hIEGlobals;
- if (pGlobals->textStyle != nil)
- GXDisposeStyle(pGlobals->textStyle);
-
- (*hIEGlobals)->textStyle = GXCloneStyle(textStyle);
-
- /** Note that the font is up to date so we don't reset it needlessly **/
-
- (*hIEGlobals)->ieStateFlags &= ~eFontOutOfDate;
-
- failed_SelectFont:
- failed_SetBaseFont:
- failed_Face:
- failed_variations:
- failed_rdFlush1:
- failed_FindFont:
- failed_FixGraphicsState:
- failed_EqualVariations:
- failed_EqualFace:
- failed_FHMFA:
- failed_rdFlush:
- failed_getfont:
-
- return(status);
-
- }//TextStylePrimitive
-
-